#include "fHeap.h"
#include "random"
#include "ctime"
#define BOOST_TEST_MAIN test
#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_CASE(Extract_Min_Test)
{
    int testSize = 10000;
    fHeap<int,int> f;
    srand (time(NULL));
    std::vector<int> v (testSize,0);
    for (int i = 0; i < testSize; i++){
        int n = abs(rand()%testSize);
        while (v[n] == 1){
            n = abs(rand()%testSize);
        }
        v[n] = 1;
        f.insert(n,n);
    }
    for(int i = 0; i< testSize - 1; i++){
        BOOST_CHECK_EQUAL(f.minimum().second, i);
        f.extractMinimum();
    }
    BOOST_CHECK_EQUAL(f.extractMinimum().first,ET_HeapIsEmpty);
    BOOST_CHECK_EQUAL(f.extractMinimum().first,ET_HeapIsEmpty);
    BOOST_CHECK_EQUAL(f.extractMinimum().first,ET_HeapIsEmpty);
}

BOOST_AUTO_TEST_CASE(Decrease_Priority_Test)
{
    int testSize = 10000;
    fHeap<int,int> f;
    srand (time(NULL));
    std::vector<int> v (testSize,0);
    for (int i = 0; i < testSize; i++){
        int n = abs(rand()%testSize);
        while (v[n] == 1){
            n = abs(rand()%testSize);
        }
        v[n] = 1;
        fHeap<int,int>::nodeHandle ptr = f.insert(n,n);
        BOOST_CHECK_EQUAL(f.decreaseKey(ptr,n+1),ET_TooBigPriority);
        f.decreaseKey(ptr,-1*n);
    }
    for(int i = 0; i< testSize - 1; i++){
        BOOST_CHECK_EQUAL(f.minimum().second,testSize - i - 1);
        f.extractMinimum();
    }

    BOOST_CHECK_EQUAL(f.extractMinimum().first,ET_HeapIsEmpty);
    BOOST_CHECK_EQUAL(f.extractMinimum().first,ET_HeapIsEmpty);
    BOOST_CHECK_EQUAL(f.extractMinimum().first,ET_HeapIsEmpty);
}

BOOST_AUTO_TEST_CASE(Remove_Nodes_Test)
{
    int testSize = 10000;
    fHeap<int,int> f;
    srand (time(NULL));
    vector<int> v (testSize,0);
    vector<fHeap<int,int>::nodeHandle> p (testSize);
    for (int i = 0; i < testSize; i++){
        int n = abs(rand()%testSize);
        while (v[n] == 1){
            n = abs(rand()%testSize);
        }
        v[n] = 1;
        fHeap<int,int>::nodeHandle ptr = f.insert(n,n);
        p[n] = ptr;
    }
    for(int i = 0; i< testSize; i++){
        BOOST_CHECK_EQUAL(f.deleteNode(p[i]),ET_NoError);
    }
    BOOST_CHECK_EQUAL(f.extractMinimum().first,ET_HeapIsEmpty);
}

BOOST_AUTO_TEST_CASE(Union_Heaps_Test)
{
    int testSize = 10000;
    fHeap<int,int> f1;
    fHeap<int,int> f2;
    srand (time(NULL));
    vector<int> v1 (testSize,0);
    vector<int> v2 (testSize,0);
    for (int i = 0; i < testSize; i++){
        int n = abs(rand()%testSize);
        while (v1[n] == 1){
            n = abs(rand()%testSize);
        }
        v1[n] = 1;
        f1.insert(n,n);
    }
    for (int i = 0; i < testSize; i++){
        int n = testSize + abs(rand()%testSize);
        while (v2[n-testSize] == 1){
            n = testSize + abs(rand()%testSize);
        }
        v2[n - testSize] = 1;
        f2.insert(n,n);
    }
    f1.unionHeaps(f2);
    for(int i = 0; i < 2*testSize-1; i++){
        BOOST_CHECK_EQUAL(f1.extractMinimum().second,i+1);
    }
    BOOST_CHECK_EQUAL(f1.minimum().second,2*testSize-1);
    BOOST_CHECK_EQUAL(f1.extractMinimum().first,ET_HeapIsEmpty);
}
